﻿using System.Collections.Generic;

namespace IFramework
{
    public class View : IView
    {
        protected IDictionary<string, IMediator> mediatorMap;//缓存IMediator实例集合
        protected IDictionary<string, IList<IPureObserver>> observerMap;
        protected static volatile IView instance;    
        protected readonly object syncRoot = new object();
        protected static readonly object staticSyncRoot = new object();

		protected View()
		{
			mediatorMap = new Dictionary<string, IMediator>();
			observerMap = new Dictionary<string, IList<IPureObserver>>();
            InitializeView();
		}
        static View(){}
		public static IView Instance
		{
			get
			{
				if (instance == null)
				{
					lock (staticSyncRoot)
					{
						if (instance == null) instance = new View();
					}
				}
				return instance;
			}
		}
        protected virtual void InitializeView(){ }

		public virtual void RegisterObserver(string notificationName, IPureObserver observer)
		{            
			lock (syncRoot)
			{
				if (!observerMap.ContainsKey(notificationName))
				{
					observerMap[notificationName] = new List<IPureObserver>();
				}
				observerMap[notificationName].Add(observer);
			}
		}
		public virtual void NotifyObservers(INotification notification)
		{
			IList<IPureObserver> observers = null;
			lock (syncRoot)
			{
				if (observerMap.ContainsKey(notification.Name))
				{
					IList<IPureObserver> observers_ref = observerMap[notification.Name];
					observers = new List<IPureObserver>(observers_ref);
				}
			}
			if (observers != null)
			{
				for (int i = 0; i < observers.Count; i++)
				{
					IPureObserver observer = observers[i];
					observer.NotifyObserver(notification);
				}
			}
		}
		public virtual void RemoveObserver(string notificationName, object notifyContext)
		{
			lock (syncRoot)
			{
				if (observerMap.ContainsKey(notificationName))
				{
					IList<IPureObserver> observers = observerMap[notificationName];
					for (int i = 0; i < observers.Count; i++)
					{
						if (observers[i].CompareNotifyContext(notifyContext))
						{
							observers.RemoveAt(i);
							break;
						}
					}
					if (observers.Count == 0)
					{
						observerMap.Remove(notificationName);
					}
				}
			}
		}

		public virtual void RegisterMediator(IMediator mediator)
		{
			lock (syncRoot)
			{
				if (mediatorMap.ContainsKey(mediator.MediatorName)) return;
				mediatorMap[mediator.MediatorName] = mediator;
				IList<string> interests = mediator.ListNotificationInterests();
				if (interests.Count > 0)
				{
					IPureObserver observer = new Observer("handleNotification", mediator);
					for (int i = 0; i < interests.Count; i++)
					{
						RegisterObserver(interests[i].ToString(), observer);
					}
				}
			}
			mediator.OnRegister();
		}
		public virtual IMediator RetrieveMediator(string mediatorName)
		{
			lock (syncRoot)
			{
				if (!mediatorMap.ContainsKey(mediatorName)) return null;
				return mediatorMap[mediatorName];
			}
		}
		public virtual IMediator RemoveMediator(string mediatorName)
		{
			IMediator mediator = null;
			lock (syncRoot)
			{
				if (!mediatorMap.ContainsKey(mediatorName)) return null;
				mediator = (IMediator) mediatorMap[mediatorName];
				IList<string> interests = mediator.ListNotificationInterests();
				for (int i = 0; i < interests.Count; i++)
				{
					RemoveObserver(interests[i], mediator);
				}
                mediatorMap.Remove(mediatorName);
			}
			if (mediator != null) mediator.OnRemove();
			return mediator;
		}
		public virtual bool HasMediator(string mediatorName)
		{
			lock (syncRoot)
			{
				return mediatorMap.ContainsKey(mediatorName);
			}
		}

	}
}
